package model.player;

import java.util.LinkedList;
import java.util.List;

import model.map.GameTile;
import model.playable.Playable;
import model.playable.unit.Melee;
import model.playable.unit.Unit;

public class MeleeManager extends UnitManager
{
	private Melee[] units;
	private int grabPointer;
	private int fillPointer;
	private int attackMod, defAttMod, armorMod, hpMod, moveMod, upkeepMod, visMod, infRadMod;
	private List<String> walkableTerrains;
	
	public MeleeManager(Player player, ResourceManager rm, List<String> walkableTerrains)
	{
		super(player, rm, "Melee");
		this.walkableTerrains = walkableTerrains;
		units = new Melee[10];
		grabPointer = 0;
		fillPointer = 0;
		attackMod = defAttMod = armorMod = hpMod = moveMod = upkeepMod = visMod = infRadMod = 0;
	}
	
	
	
	@Override
	public void createNewUnit(GameTile tile)
	{
		if (isFull())
			throw new RuntimeException("Cannot add any more Melee units");
		
		Melee u = new Melee(super.getPlayer(), walkableTerrains);
		u.incrementArmor(armorMod);
		u.incrementDefensiveDamage(defAttMod);
		u.incrementHealth(hpMod);
		u.incrementInfluenceRadius(infRadMod);
		u.incrementMovementSpeed(moveMod);
		u.incrementOffensiveDamage(attackMod);
		u.incrementUpkeep(upkeepMod);
		u.incrementVisibilityRadius(visMod);
		
		goToNextFillSpot();
		u.setIdNumber(fillPointer);
		
		units[fillPointer++] = u;
		
		super.addUnitToMap(tile, u);
	}

	private void goToNextFillSpot() 
	{
		if (isEmpty())
		{
			fillPointer = 0;
			return;
		}
		
		while (units[fillPointer%units.length] != null )
		{
			fillPointer = (fillPointer +1) % units.length;
		}
		
	}



	@Override
	public void payUpkeep() 
	{
		for (Unit u: units)
			if (u != null)
			{
				u.addUpkeep(super.grabFood(u.getUpkeep()));
			}
		
	}
	
	public void remove(int i)
	{
		if (units[i] != null)
			super.removeFromMap(units[i]);
		units[i] = null;
	}

	@Override
	public Playable getCurPlayable() 
	{
		
		while (units[grabPointer] == null)
		{
			grabPointer = (grabPointer +1) % units.length;
		}
		return units[grabPointer];
	}

	@Override
	public Playable getNextPlayable() 
	{
		grabPointer = (grabPointer +1) % units.length;
		
		while (units[grabPointer] == null)
		{
			grabPointer = (grabPointer +1) % units.length;
		}
		return units[grabPointer];
	}

	@Override
	public Playable getPrevPlayable() 
	{
		
		grabPointer = (grabPointer -1 + units.length) % units.length;
		
		while (units[grabPointer] == null)
		{
			grabPointer = (grabPointer -1 + units.length) % units.length;
		}
		return units[grabPointer];
	}

	@Override
	public void upgradeArmorStat() 
	{
		armorMod++;
		for (Melee u : units)
		{
			if (u != null)
				u.incrementArmor(1);
		}
	}

	@Override
	public void upgradeAttackStat() 
	{
		attackMod++;
		for (Melee u : units)
		{
			if (u != null)
				u.incrementOffensiveDamage(1);
		}
	}

	@Override
	public void upgradeDefAttackStat() 
	{
		defAttMod++;
		for (Melee u : units)
		{
			if (u != null)
				u.incrementDefensiveDamage(1);
		}
	}

	@Override
	public void upgradeHealthStat() 
	{
		hpMod++;
		for (Melee u : units)
		{
			if (u != null)
				u.incrementHealth(1);
		}
	}

	@Override
	public void upgradeMovementStat() 
	{
		moveMod++;
		for (Melee u : units)
		{
			if (u != null)
				u.incrementMovementSpeed(1);
		}
	}

	@Override
	public void upgradeUpkeepStat() 
	{
		upkeepMod++;
		for (Melee u : units)
		{
			if (u != null)
				u.incrementUpkeep(1);
		}
	}

	@Override
	public void upgradeVisibilityStat() 
	{
		visMod++;
		for (Melee u : units)
		{
			if (u != null)
				u.incrementVisibilityRadius(1);
		}
	}

	@Override
	public void upgradeInfluenceRadiusStat() 
	{
		infRadMod++;
		for (Melee u : units)
		{
			if (u != null)
				u.incrementInfluenceRadius(1);
		}
	}



	@Override
	public boolean isEmpty() 
	{
		for (Unit u : units)
			if (u != null)
				return false;
		
		return true;
	}



	@Override
	public boolean isFull()
	{
		for (Unit u : units)
			if (u == null)
				return false;
		
		return true;
	}



	@Override
	public Playable getPlayableID(int id) 
	{
		return units[id];
	}
	
	@Override
	public void update()
	{
		for (Unit u : units)
			if (u != null)
				u.executeCommand();
		payUpkeep();
	}

	@Override
	public List<Unit> getAllUnits() 
	{
		List<Unit> result = new LinkedList<Unit>();
		
		for (Unit u : units)
			if (u != null)
				result.add(u);
		
		return result;
	}
	
	@Override
	public Unit getUnit(int id) 
	{
		return units[id];
	}
}
